using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Autofac;
using Cysharp.Threading.Tasks;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace ModuleManager
{
    /// <summary>
    /// 模块启动管理器
    /// </summary>
    // ReSharper disable once ClassNeverInstantiated.Global
    public class ModuleManager : ModuleStartUpBase, IModuleManager
    {
        private readonly ICollection<Type> _moduleStartUpTypeCollection;
        private readonly ILifetimeScope _scope;
        private readonly Stack<IModuleStartUp> _moduleStartUpList = new Stack<IModuleStartUp>();

        /// <summary>
        /// 模块启动管理器
        /// </summary>
        /// <param name="moduleStartUpTypeCollection">每个模块中的StartUp的启动顺序集合。模块中的每个IModuleStartUp的StartAsync函数会按照这个集合的顺序进行启动</param>
        /// <param name="scope"></param>
        public ModuleManager(ICollection<Type> moduleStartUpTypeCollection, ILifetimeScope scope)
        {
            _moduleStartUpTypeCollection = moduleStartUpTypeCollection;
            _scope = scope;
        }

        public override async UniTask<bool> StartAsync(object context)
        {
            try
            {
                foreach (var startUpType in _moduleStartUpTypeCollection)
                {
                    var moduleStartUp = (IModuleStartUp)_scope.Resolve(startUpType);
                    _moduleStartUpList.Push(moduleStartUp);
                    var next = await StartModuleStartUpAsync(context, moduleStartUp);
                    if (!next)
                        return false;
                }

                var all = _scope.Resolve<IEnumerable<IModuleStartUp>>();
                var rest = all.Except(_moduleStartUpList);
                foreach (var startUp in rest)
                {
                    _moduleStartUpList.Push(startUp);
                    await StartModuleStartUpAsync(context, startUp);
                }

                return true;
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                throw;
            }
        }
        private async UniTask<bool> StartModuleStartUpAsync(object context, IModuleStartUp moduleStartUp)
        {
            var sw = new Stopwatch();
            sw.Start();
            Debug.Log($"开始执行ModuleStartUp的StartUp， ModuleStartUp type:{moduleStartUp.GetType()}");
            
            var result = await moduleStartUp.StartAsync(context);
            
            sw.Stop();
            Debug.Log($"结束执行ModuleStartUp的StartUp， ModuleStartUp type:{moduleStartUp.GetType()}， 耗时：{sw.ElapsedMilliseconds}");
            return result;
        }

        public override async UniTask StopAsync()
        {
            try
            {
                while (_moduleStartUpList.Count > 0)
                {
                    var moduleStartUp = _moduleStartUpList.Pop();
                    await moduleStartUp.StopAsync();
                    Debug.Log($"开始执行Module的StopAsync， ModuleStartUp type:{moduleStartUp.GetType()}");
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                throw;
            }
        }
    }
}